一、准备工作
最近在做的一个vue项目中,需要做一个分享海报,头秃!!! 首先确定海报那些地方是随机变动的、海报背景、引用二维码生成组件(目前市场上有很多生成二维码的组件,这个项目用的是uqrcode)注意小程序中分享二维码需要现在小程序后台开发设置中配好,不然链接进不去对应小程序中。
//判断昵称信息是否是中文
isChinese(size) {
var re = /[^\u4E00-\u9FA5]/;
let chartLength=0;
for(let i=0;i {
that.shareObj[type] = res.path
resolve()
}
})
})
},
//获取设备信息
getSys() {
let that = this;
return new Promise(function(resolve, reject) {
//获取系统信息
wx.getSystemInfo({
success: function(res) {
resolve(res.windowWidth / 750)
}
})
})
},
//生成二维码
async qrcode() {
await this.$refs.uqrcode.make({
mode: 'canvas', // 默认为view
// size: 40, //尺寸 以px为单位
// text: '*****', //测试网址内容如:https://www.baidu.com 必须在微信公众平台上配置好,不然扫码打开的为404网页
}).then(res => {
// 返回的res与uni.canvasToTempFilePath返回一致
this.shareObj.codeUrl = res.tempFilePath
})
},
开始生成海报
let that = this;
var company = 1
wx.showLoading({
title: '生成海报中...'
})
//获取设备信息
company = await that.getSys()
//获取头像等图片信息
await that.getImage(that.userInfo.avatar, 'avatarUrl')
//由于小程序限制2M以内,不能放置较大的背景图片在本地,并且ctx.drawImage中的url必须是本地url,所以使用线上图片需要获取图片本地信息。
await that.getImage('https://cdn.vchen.cc/applets/guide/share-bcg.png', 'bcgUrl')
//生成二维码,必须等待这些工作完成才能开始创建海报、不然会报错
await that.qrcode()
//创建canvas实例对象
const ctx = wx.createCanvasContext('shareCanvas', that)
//定义头像、二维码变量
let avartarObj = {
wid: 188 * company,
hei: 188 * company,
x: 237 * company,
y: 177 * company,
},
codeObj = {
wid: 114 * company,
hei: 114 * company,
x: 274 * company,
y: 779 * company,
},
//计算昵称长度
nameLength = (669 - that.isChinese(42) - 3 * 42) / 2
//绘制海报背景
ctx.drawImage(that.shareObj.bcgUrl, 0, 0, 669 * company, 975 * company);
//绘制海报中固定的图片
ctx.drawImage('/static/login/[email protected]', 158 * company, 485 * company, 359 * company, 56 * company);
二、海报生成
// 生成海报
async createCanvasImage() {
let that = this;
var company = 1
//判断是否已经生成海报
if (that.shareObj.canvasToTempFilePath != '') {
that.shareShow = true
return
}
wx.showLoading({
title: '生成海报中...'
})
//获取系统信息,得到比列单位值,可以适配海报尺寸
company = await that.getSys()
//获取头像等图片信息
await that.getImage(that.userInfo.avatar, 'avatarUrl')
await that.getImage('https://cdn.vchen.cc/applets/guide/share-bcg.png', 'bcgUrl')
//绘制二维码要先生成二维码,在塞入海报中,不然容易报错
await that.qrcode()
const ctx = wx.createCanvasContext('shareCanvas', that)
let avartarObj = {
wid: 188 * company,
hei: 188 * company,
x: 237 * company,
y: 177 * company,
},
codeObj = {
wid: 114 * company,
hei: 114 * company,
x: 274 * company,
y: 779 * company,
},
//根据昵称长度计算出名字的水平居中位置
nameLength = (669 - that.isChinese(42) - 3 * 42) / 2
//绘制海报背景图
ctx.drawImage(that.shareObj.bcgUrl, 0, 0, 669 * company, 975 * company);
//绘制海报中固定图片
ctx.drawImage('/static/login/[email protected]', 158 * company, 485 * company, 359 * company, 56 * company);
ctx.save(); // 先保存状态 已便于画完圆再用
ctx.beginPath(); //开始绘制
//先画个圆 前两个参数确定了圆心 (x,y) 坐标 第三个参数是圆的半径 四参数是绘图方向 默认是false,即顺时针
ctx.arc(avartarObj.wid / 2 + avartarObj.x, avartarObj.hei / 2 + avartarObj.y, avartarObj.wid / 2, 0, Math
.PI * 2, false);
ctx.clip(); //画了圆 再剪切 原始画布中剪切任意形状和尺寸。一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内
ctx.drawImage(that.shareObj.avatarUrl, avartarObj.x, avartarObj.y, avartarObj.wid,
avartarObj.hei); // 推进去图片
ctx.restore(); //恢复之前保存的绘图上下文状态 可以继续绘制
//文字
ctx.font = 'normal 400 42px SimHei';
ctx.setFillStyle('black'); // 文字颜色
ctx.setFontSize(42 * company); // 文字字号
ctx.fillText(that.userInfo.name + ' 同学', nameLength * company, 415 *
company); // 绘制文字
//文字
ctx.font = 'normal 400 25px SimHei';
ctx.setFillStyle('#322B2B'); // 文字颜色
ctx.setFontSize(25 * company); // 文字字号
ctx.fillText('在好好学习的', 243 * company, 448 * company); // 绘制文字
ctx.font = 'normal 400 25px SimHei';
ctx.setFillStyle('#322B2B'); // 文字颜色
ctx.setFontSize(25 * company); // 文字字号
ctx.fillText('学塾中表现优秀', 243 * company, 478 * company); // 绘制文字
//绘制二维码留白区域
ctx.fillStyle = "#fff"
ctx.fillRect(268 * company, 773 * company, 127 * company, 147 * company);
//绘制文字
ctx.font = 'normal 400 17px KaiTi';
ctx.setFillStyle('#322B2B'); // 文字颜色
ctx.setFontSize(17 * company); // 文字字号
ctx.fillText("扫码进入小程序", 274 * company, 915 * company); // 二维码提示
ctx.drawImage(that.shareObj.codeUrl, codeObj.x, codeObj.y, codeObj.wid, codeObj.hei); // 绘制二维码
//获取canvas画布转图片地址 以下加setTimeout 是为了解决文字样式错乱问题
await new Promise((resolve, reject) => ctx.draw(false, () => setTimeout(() => resolve(), 500)));
wx.canvasToTempFilePath({
canvasId: 'shareCanvas',
success: function(res) {
that.shareObj.canvasToTempFilePath = res.tempFilePath
that.shareShow = true//显示海报
wx.showToast({
title: '生成海报成功',
})
},
fail: function() {
wx.showToast({
title: '生成海报失败',
})
that.shareShow = false
},
complete: function() {
wx.hideLoading()
wx.hideToast()
}
}, that)
},
三、保存图片
// 保存到系统相册的授权
saveShareImg() {
let that = this;
// 获取用户当前设置
uni.getSetting({
success(res) {
that.shareObj.openStatus = res.authSetting['scope.writePhotosAlbum'] || null
}
})
if (!that.shareObj.openStatus) {
uni.authorize({
scope: 'scope.writePhotosAlbum',
success() {
that.saveImg()
},
fail() {
that.$refs.uToastCode.show('请先授权,才能保存图片')
}
})
} else {
that.saveImg()
}
},
//保存到相册
saveImg() {
let that = this
uni.saveImageToPhotosAlbum({
filePath: that.shareObj.canvasToTempFilePath,
success: function() {
let token = uni.getStorageSync(that.$constants.STORAGE_AUTH_TOKEN)
if (token) {
let result = that.$u.api.integral.share();
}
that.$refs.uToastCode.show({
title: '保存成功',
type: 'success'
})
},
fail() {
that.$refs.uToastCode.show({
title: '保存失败',
type: 'success'
})
},
complete() {
that.shareShow = false
that.toHome()
}
});
}
|